/**
 * 根据选择器查找满足条件的第一个元素
 * @param selector 选择器
 * @return 满足选择器条件的第一个元素
 */
function $(selector) {
    return document.querySelector(selector)
}

/**
 *多属性运动动画函数
 * @param {*} element 待添加运动动画效果的DOM元素
 * @param {*} options 存放要实现动画效果的属性以及该属性的最终值的对象
 * @param {*} duration 限定运动的总时长
 * @param {*} fn 可选参数，动画执行完后需要调用的函数
 */
function animate(element, options, duration, fn) {
    clearInterval(element.timer)
    const start = {}
    const speed = {}
    for (const key in options) {
        start[key] = parseFloat(window.getComputedStyle(element, null)[key])
        speed[key] = (options[key] - start[key]) / duration
    }
    const startTime = Date.now()

    function move() {
        const elapsed = Math.min(duration, Date.now() -
            startTime)
        for (const key in options) {
            const result = elapsed * speed[key] + start[key]
            element.style[key] = result + (key === 'opacity' ? '' : 'px')
        }
        if (elapsed !== duration) {
            element.timer = setTimeout(move, 1000 / 60)
        } else {
            fn && fn()
        }
    }
    move()
}
/**
 *淡入效果函数
 * @param {*} element 执行淡入效果的元素
 * @param {*} duration 淡入效果时长
 * @param {*} fn
 */
function fadeIn(element,duration,fn){
    element.style.display = 'block'
    element.style.opacity = 0
    animate(element, {opacity: 1}, duration, fn)
}
/**
 *淡出效果函数
 * @param {*} element 执行淡出效果的元素
 * @param {*} duration 淡出效果时长
 * @param {*} fn
 */
function fadeOut(element,duration,fn){
    animate(element, {opacity: 0}, duration, () => {
        element.style.display = 'none'
        fn && fn()
      })
}

/**
 *产生一个min~max范围内的随机整数
 * @param {*} min 随机数的最小值
 * @param {*} max 随机数的最大值
 * @return {*} 返回生成的随机数
 */
function random(min, max) {
    return Math.floor(Math.random() * (max - min)) + min
}


//以下为兼容性适配
/**
 * 根据类名查找元素
 * @param {*} className 类名
 * @return 根据类名查找到的元素数组（类数组对象）
 */
function getElementsByClassName(className) {
    // 支持，则直接使用
    if (document.getElementsByClassName) {
        return document.getElementsByClassName(className)
    }
    // 不支持，实现兼容写法
    var result = []
    var tags = document.getElementsByTagName('*')
    for (var i = 0, len = tags.length; i < len; i++) {
        // 当前遍历到元素使用的所有类名
        var classNames = tags[i].className.split(' ')
        // 遍历所有类名
        for (var j = 0, l = classNames.length; j < l; j++) {
            if (classNames[j] === className) {
                result.push(tags[i])
                break
            }
        }
    }
    return result
}

/**
 * 获取或设置 css 样式
 * @param element DOM 元素节点
 * @param name CSS 属性名称
 * @param value CSS 属性值
 */
function css(element, name, value) {
    // value 参数未传递
    if (typeof value === 'undefined') {
        // 根据属性名获取属性值
        if (typeof name === 'string') {
            // 根据 css 属性名获取对应属性值
            if (window.getComputedStyle) {
                return window.getComputedStyle(element, null)[name]
            }
            return element.currentStyle[name] // IE9 之前
        } else if (typeof name === 'object') {
            // 设置 css 样式
            for (var key in name) {
                element.style[key] = name[key]
            }
            return
        }
    }
    // 设置 css 样式
    element.style[name] = value
}

/**
 * 注册事件监听
 * @param {*} element
 * @param {*} eventType
 * @param {*} callback
 */
function on(element, eventType, callback) {
    if (element.addEventListener) {
        element.addEventListener(eventType, callback, false)
    } else {
        eventType = 'on' + eventType
        element.attachEvent(eventType, callback)
    }
}

/**
 * 移除事件监听
 * @param {*} element
 * @param {*} eventType
 * @param {*} callback
 */
function off(element, eventType, callback) {
    if (element.removeEventListener) {
        element.removeEventListener(eventType, callback, false)
    } else {
        eventType = 'on' + eventType
        element.detachEvent(eventType, callback)
    }
}
